package com.zhijian.medical.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Sets;
import com.zhijian.medical.dao.local.PcrHszbqMapper;
import com.zhijian.medical.entity.dto.PcrHskzyqWzDto;
import com.zhijian.medical.entity.dto.PcrHszbqFykDto;
import com.zhijian.medical.entity.po.ExperimentProcessSample;
import com.zhijian.medical.entity.po.ExperimentProcessSampleLog;
import com.zhijian.medical.entity.po.Pcr;
import com.zhijian.medical.entity.po.PcrHszbq;
import com.zhijian.medical.entity.vo.request.ExperimentProcessSampleSearchVo;
import com.zhijian.medical.entity.vo.request.PcrHszbqSaveOrUpdateVo;
import com.zhijian.medical.entity.vo.request.PcrHszbqSearchVo;
import com.zhijian.medical.entity.vo.response.ExperimentProcessSampleVo;
import com.zhijian.medical.entity.vo.response.PcrHszbqVo;
import com.zhijian.medical.enums.*;
import com.zhijian.medical.holder.CurrentUserHolder;
import com.zhijian.medical.service.ExperimentProcessSampleLogService;
import com.zhijian.medical.service.ExperimentProcessSampleService;
import com.zhijian.medical.service.PcrHszbqService;
import com.zhijian.medical.service.PcrService;
import com.zhijian.medical.util.AssertUtil;
import com.zhijian.medical.util.JsonUtil;
import com.zhijian.medical.util.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 荧光PCR-核酸制备区业务处理层
 *
 * @author HCG
 * @version: 1.0
 * @date 2022-08-30 15:34:57
 */
@Slf4j
@Service
public class PcrHszbqServiceImpl implements PcrHszbqService {

    @Autowired
    private PcrHszbqMapper mapper;

    @Autowired
    private PcrService pcrService;

    @Autowired
    private ExperimentProcessSampleService experimentProcessSampleService;

    @Autowired
    private ExperimentProcessSampleLogService experimentProcessSampleLogService;

    @Override
    public PcrHszbq selectById(Long id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public PcrHszbq selectByPcrId(Long pcrId) {
        return mapper.selectByPcrId(pcrId);
    }

    @Override
    public PcrHszbqVo selectVoById(Long id) {
        return mapper.selectVoById(id);
    }

    @Override
    public PcrHszbqVo selectVoByPcrId(Long pcrId) {
        PcrHszbqVo pcrHszbqVo = mapper.selectVoByPcrId(pcrId);
        if (Objects.isNull(pcrHszbqVo)) {
            return null;
        }
        Pcr pcr = pcrService.selectById(pcrId);
        if (Objects.isNull(pcr)) {
            return null;
        }
        Byte type = pcr.getType();
        PcrTypeEnum pcrTypeEnum = PcrTypeEnum.getByCode(type.intValue());
        AssertUtil.notNull(pcrTypeEnum, "类型非法");
        assert pcrTypeEnum != null;
        switch (pcrTypeEnum) {
            case KNB:
                pcrHszbqVo.setResult(pcr.getStatus() > PcrKnbStatusEnum.HSZBQ.getCode().byteValue() ?
                        AllExperimentationStepStatusEnum.END.getCode().byteValue() : AllExperimentationStepStatusEnum.UN_END.getCode().byteValue());
                pcrHszbqVo.setResultStr(pcr.getStatus() > PcrKnbStatusEnum.HSZBQ.getCode().byteValue() ?
                        AllExperimentationStepStatusEnum.END.getDesc() : AllExperimentationStepStatusEnum.UN_END.getDesc());
                break;
            case GW_HPV:
                break;
            case FA_5:
                break;
            case JAK2:
                break;
            case PIK3CA:
                break;
            case COV:
                pcrHszbqVo.setResult(pcr.getStatus() > PcrCovStatusEnum.HSZBQ.getCode().byteValue() ?
                        AllExperimentationStepStatusEnum.END.getCode().byteValue() : AllExperimentationStepStatusEnum.UN_END.getCode().byteValue());
                pcrHszbqVo.setResultStr(pcr.getStatus() > PcrCovStatusEnum.HSZBQ.getCode().byteValue() ?
                        AllExperimentationStepStatusEnum.END.getDesc() : AllExperimentationStepStatusEnum.UN_END.getDesc());
                break;
            default:
                pcrHszbqVo.setResult(pcr.getStatus() > PcrKnbStatusEnum.HSZBQ.getCode().byteValue() ?
                        AllExperimentationStepStatusEnum.END.getCode().byteValue() : AllExperimentationStepStatusEnum.UN_END.getCode().byteValue());
                pcrHszbqVo.setResultStr(pcr.getStatus() > PcrKnbStatusEnum.HSZBQ.getCode().byteValue() ?
                        AllExperimentationStepStatusEnum.END.getDesc() : AllExperimentationStepStatusEnum.UN_END.getDesc());
                break;
        }

        List<ExperimentProcessSampleVo> experimentProcessSampleVos = experimentProcessSampleService.selectList(ExperimentProcessSampleSearchVo.builder()
                .experimentProcessId(pcrId)
                .mainType(ExperimentTypeEnum.PCR.getCode().byteValue())
                .build());
        pcrHszbqVo.setExperimentProcessSampleList(experimentProcessSampleVos);
        //反应孔数据
        String fykData = pcrHszbqVo.getFykData();
        if (StringUtils.isNotBlank(fykData)) {
            pcrHszbqVo.setFykDataList(JsonUtil.toArray(fykData, PcrHszbqFykDto.class));
        }
        return pcrHszbqVo;
    }

    @Override
    public void deleteById(Long id) {
        mapper.deleteByPrimaryKey(id);
    }

    @Override
    public void deleteByPcrId(Long pcrId) {
        mapper.deleteByPcrId(pcrId);
    }

    @Override
    public Long insert(PcrHszbq pcrHszbq) {
        Date now = new Date();
        pcrHszbq.setCreateTime(now);
        pcrHszbq.setUpdateTime(now);
        if (Objects.isNull(pcrHszbq.getHszbqhstqsyqsystmqj())) {
            pcrHszbq.setHszbqhstqsyqsystmqj(StatusEnum.UN_NORMAL.getCode().byteValue());
        }
        if (Objects.isNull(pcrHszbq.getHszbqhstqhstqsjsjzyxqn())) {
            pcrHszbq.setHszbqhstqhstqsjsjzyxqn(StatusEnum.UN_NORMAL.getCode().byteValue());
        }
        if (Objects.isNull(pcrHszbq.getHszbqhstqsjzzdgqjxhgcywyc())) {
            pcrHszbq.setHszbqhstqsjzzdgqjxhgcywyc(StatusEnum.UN_NORMAL.getCode().byteValue());
        }
        if (Objects.isNull(pcrHszbq.getHszbqhstqhstqgcgcywyc())) {
            pcrHszbq.setHszbqhstqhstqgcgcywyc(StatusEnum.UN_NORMAL.getCode().byteValue());
        }
        if (Objects.isNull(pcrHszbq.getHszbqhstqyqsbsyqktsgslxj())) {
            pcrHszbq.setHszbqhstqyqsbsyqktsgslxj(StatusEnum.NORMAL.getCode().byteValue());
        }
        if (Objects.isNull(pcrHszbq.getHszbqhstqyqsbsyqkzdq())) {
            pcrHszbq.setHszbqhstqyqsbsyqkzdq(StatusEnum.NORMAL.getCode().byteValue());
        }
        if (Objects.isNull(pcrHszbq.getHszbqhstqyqsbsyqkswaqg())) {
            pcrHszbq.setHszbqhstqyqsbsyqkswaqg(StatusEnum.NORMAL.getCode().byteValue());
        }
        if (Objects.isNull(pcrHszbq.getHszbqhstqyqsbsyqkhwjsg())) {
            pcrHszbq.setHszbqhstqyqsbsyqkhwjsg(StatusEnum.NORMAL.getCode().byteValue());
        }
        if (Objects.isNull(pcrHszbq.getQzdhstqy())) {
            pcrHszbq.setQzdhstqy(StatusEnum.NORMAL.getCode().byteValue());
        }
        if (Objects.isNull(pcrHszbq.getHszbqhstqsyhqjjzwzssygztm())) {
            pcrHszbq.setHszbqhstqsyhqjjzwzssygztm(StatusEnum.UN_NORMAL.getCode().byteValue());
        }
        if (Objects.isNull(pcrHszbq.getHszbqhstqsyhjxsyqzwxzs())) {
            pcrHszbq.setHszbqhstqsyhjxsyqzwxzs(StatusEnum.UN_NORMAL.getCode().byteValue());
        }
        if (Objects.isNull(pcrHszbq.getHszbqhstqsyhclsyfqw())) {
            pcrHszbq.setHszbqhstqsyhclsyfqw(StatusEnum.UN_NORMAL.getCode().byteValue());
        }
        return mapper.insert(pcrHszbq) > 0 ? pcrHszbq.getId() : 0L;
    }

    @Override
    public boolean update(PcrHszbq pcrHszbq) {
        Date now = new Date();
        pcrHszbq.setUpdateTime(now);
        return mapper.updateByPrimaryKey(pcrHszbq) != 0;
    }

    @Override
    public Integer count(PcrHszbqSearchVo pcrHszbqSearchVo) {
        return mapper.count(pcrHszbqSearchVo);
    }

    @Override
    public List<PcrHszbqVo> selectList(PcrHszbqSearchVo pcrHszbqSearchVo) {
        return mapper.selectList(pcrHszbqSearchVo);
    }

    @Override
    public Page<PcrHszbqVo> selectPage(PcrHszbqSearchVo pcrHszbqSearchVo) {
        //先直接查总数
        int count = count(pcrHszbqSearchVo);
        //分页
        Page<PcrHszbqVo> page = new Page<>(true, count, pcrHszbqSearchVo.getPageNum(), pcrHszbqSearchVo.getPageSize());
        pcrHszbqSearchVo.setStartIndex(page.getStartIndex());
        page.setPage(true);
        page.setTotalCount(count);
        List<PcrHszbqVo> responseVos = this.selectList(pcrHszbqSearchVo);
        page.setData(responseVos);
        return page;
    }

    @Transactional(rollbackFor = Exception.class, value = "localTransactionManager")
    @Override
    public boolean saveOrUpdate(PcrHszbqSaveOrUpdateVo pcrHszbqSaveOrUpdateVo) {
        Long pcrId = pcrHszbqSaveOrUpdateVo.getPcrId();
        Pcr pcr = pcrService.selectById(pcrId);
        AssertUtil.notNull(pcr, "此实验不存在或者已被删除");
        Byte type = pcr.getType();
        PcrTypeEnum pcrTypeEnum = PcrTypeEnum.getByCode(type.intValue());
        AssertUtil.notNull(pcrTypeEnum, "类型非法");
        assert pcrTypeEnum != null;
        switch (pcrTypeEnum) {
            case KNB:
                if (pcr.getStatus() < PcrKnbStatusEnum.SJPZQ.getCode().byteValue()) {
                    //将实验的状态修改
                    pcrService.updateByPrimaryKeySelective(Pcr.builder()
                            .id(pcrId)
                            .status(PcrKnbStatusEnum.SJPZQ.getCode().byteValue())
                            .build());
                }
                break;
            case GW_HPV:
                break;
            case FA_5:
                break;
            case JAK2:
                break;
            case PIK3CA:
                break;
            case COV:
                if (pcr.getStatus() < PcrCovStatusEnum.HSKZYQ.getCode().byteValue()) {
                    //将实验的状态修改
                    pcrService.updateByPrimaryKeySelective(Pcr.builder()
                            .id(pcrId)
                            .status(PcrKnbStatusEnum.HSKZYQ.getCode().byteValue())
                            .build());
                }
                break;
            default:
                if (pcr.getStatus() < PcrKnbStatusEnum.SJPZQ.getCode().byteValue()) {
                    //将实验的状态修改
                    pcrService.updateByPrimaryKeySelective(Pcr.builder()
                            .id(pcrId)
                            .status(PcrKnbStatusEnum.SJPZQ.getCode().byteValue())
                            .build());
                }
                break;
        }

        List<PcrHszbqFykDto> fykDataList1 = pcrHszbqSaveOrUpdateVo.getFykDataList();
        //要这个来判定是否含有重复样本
        Set<String> fzblhSet = Sets.newHashSet();
        if (CollectionUtil.isNotEmpty(fykDataList1)) {
            fykDataList1.forEach(f2 -> {
                List<List<PcrHskzyqWzDto>> f = f2.getData();
                if (CollectionUtil.isNotEmpty(f)) {
                    f.forEach(f3 -> f3.stream().filter(f1 -> StringUtils.isNotBlank(f1.getFzblh())).forEach(f1 -> {
                        String fzblh = f1.getFzblh();
                        AssertUtil.check(!fzblhSet.add(fzblh), "反应孔数据不允许有重复分子病理号");
                        if (StringUtils.isBlank(f1.getProject())) {
                            //如果有项目号，就直接不查了
                            ExperimentProcessSample experimentProcessSample = experimentProcessSampleService.selectByFzblh(fzblh);
                            if (Objects.nonNull(experimentProcessSample)) {
                                AssertUtil.check(!Objects.equals(experimentProcessSample.getExperimentProcessId(), pcrId), String.format("分子病理号为%s的样本不存在于此次实验流程", experimentProcessSample.getMoleculePathologyNumber()));
                                f1.setProject(ExperimentTypeEnum.PCR.getProject().get(7));
                            }
                        }
                    }));

                }
            });
            pcrHszbqSaveOrUpdateVo.setFykData(JsonUtil.toString(fykDataList1));
        }

        PcrHszbq dbParam = new PcrHszbq();
        BeanUtils.copyProperties(pcrHszbqSaveOrUpdateVo, dbParam);
        PcrHszbq oldPcrHszbq = this.selectByPcrId(pcrHszbqSaveOrUpdateVo.getPcrId());
        if (Objects.isNull(oldPcrHszbq)) {
            this.insert(dbParam);
        } else {
            dbParam.setId(oldPcrHszbq.getId());
            this.update(dbParam);
        }
        List<ExperimentProcessSampleVo> experimentProcessSampleVos = experimentProcessSampleService.selectList(ExperimentProcessSampleSearchVo.builder()
                .mainType(ExperimentTypeEnum.PCR.getCode().byteValue())
                .experimentProcessId(pcrId)
                .build());
        //保存样本日志
        experimentProcessSampleLogService.saveBatch(experimentProcessSampleVos.stream().map(e -> ExperimentProcessSampleLog.builder()
                .sampleId(e.getId())
                .fishId(pcrId)
                .mainType(ExperimentTypeEnum.PCR.getCode().byteValue())
                .op(String.format("%s%s-%s", pcr.getName(), pcr.getProcessNumber(), PcrKnbStatusEnum.HSZBQ.getDesc()))
                .opUser(CurrentUserHolder.getUser().getName())
                .build()).collect(Collectors.toList()));
        return true;
    }

}